前面十二天我們一路從無到有建了個 AI 聊天機器人,現在要準備 deploy 到 production 了,但之前的選擇造成了一些限制:
Slack Socket Mode 每個 App Token 最多只能開 10 條連線!
你沒看錯,就是 10 條!不是 100 條,不是薯條,就是 10 條!
這意味著什麼?看看我們 Day 12 的架構:
// Day 12: 全部塞在一個 process 裡
async function startSlackBolt() {
// Slack Bot 邏輯
}
async function startGenkitFlow() {
// GenKit Flow 邏輯
}
async function main() {
await Promise.all([
startGenkitFlow(),
startSlackBolt()
]);
console.log('Service Started');
}
想要 scale up?每開一個 instance 就吃掉一條 Slack 連線。想開 20 個 instance 提高可用性?對不起,第11個開始就連不上了。
更慘的是,如果你想要調整 GenKit 的 instance 數量來處理更多 AI 請求,結果 Slack 連線也跟著增加。完全是被綁架的狀態啊!
但我們在前面選擇了 Socket Mode,現在就得面對這個挑戰。
既然被 Slack 限制住了,那就拆吧!
我們現在有三個主要功能:
這三個功能的特性完全不同:
「既然特性不同,為什麼要綁在一起受罪?」
最終決定拆成三個獨立服務:
Day 12: Day 13:
src/ ├── GenKit/
index.ts │ ├── src/
package.json │ ├── config/
│ ├── prompts/
│ └── Dockerfile
├── SlackBolt/
│ ├── src/
│ └── Dockerfile
└── docker-compose.yml
MCP:
GenKit/config/mcp-config.json
可以看出來:{
"mcpServers": {
"playwright": {
"url": "http://127.0.0.1:8931/mcp"
}
}
}
Playwright 我們改用了 streamable http 模式的 MCP 了。
# docker-compose.yml
services:
genkit-service:
build:
context: ./GenKit
dockerfile: Dockerfile
container_name: genkit-service
ports:
- "3400:3400"
environment:
- SLACK_BOT_USER_ID=${SLACK_BOT_USER_ID}
- GEMINI_API_KEY=${GEMINI_API_KEY}
- GENKIT_PORT=3400
restart: unless-stopped
slack-service:
build:
context: ./SlackBolt
dockerfile: Dockerfile
container_name: slack-service
environment:
- SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN}
- SLACK_APP_TOKEN=${SLACK_APP_TOKEN}
- GENKIT_SERVICE_URL=http://genkit-service:3400
depends_on:
- genkit-service
restart: unless-stopped
playwright-mcp:
image: mcr.microsoft.com/playwright/mcp
ports:
- "8931:8931"
entrypoint: ["node"]
command: ["cli.js", "--headless", "--browser", "chromium", "--no-sandbox", "--port", "8931"]
restart: unless-stopped
現在的 calling chain 變成:
用戶 → Slack Service → GenKit Service → MCP Service → 瀏覽器
每個服務都有自己的 container,有自己的 Dockerfile,有自己的 package.json。真正的關注點分離!
擔心開發變複雜?看看根目錄的 package.json:
{
"scripts": {
"dev": "concurrently \"cd GenKit && bun run dev\" \"cd SlackBolt && bun run dev\""
},
"devDependencies": {
"concurrently": "^9.1.2"
}
}
還是一個 bun run dev
全部起來,只是現在後面跑的是兩個獨立的 process。
看看 k8s.yaml 的部分:
# GenKit Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: genkit-service
spec:
replicas: 1
---
# Slack Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: slack-service
spec:
replicas: 10 # 榨乾 Socket Mode 的極限
現在:
以前:任何一個功能掛掉 → 整個 bot 重開 → 用戶體驗爛到爆
現在:
這就是所謂的 fault isolation,一個掛不會全部陪葬。
以前所有功能都要用同樣的機器規格。現在可以:
現在三個 service 可以各自監控:
如果是團隊開發:
大家各自在自己的 service 裡面改,不會互相踩到。
從 Day 12 的到 Day 13 的微服務架構,核心就是:
✅ 突破 Slack 10 連線限制:GenKit 和 MCP 不再被拖累
✅ 各自 scale 到爽:可以依照需求 scale
✅ 故障不會全滅:一個掛了其他還能活著
✅ 資源配置客製化:每個 service 都能用最適合的 resourse
Docker Compose 在這個轉換中扮演重要角色,讓我們可以:
完整的原始碼在這裡,現在每次對話都能看到確切的成本消耗!
AI 的發展變化很快,目前這個想法以及專案也還在實驗中。但也許透過這個過程大家可以有一些經驗和想法互相交流,歡迎大家追蹤這個系列。
也歡迎追蹤我的 Threads @debuguy.dev